﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Resources;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace test
{
    public partial class Form1 : Form
    {
        public ArrayList cards;
        public ArrayList hiscards;
        public ArrayList cardsend;
        public ArrayList cardrecv;
        public Stack stack;

        public Point location;
        public Point location_playzone;       //出牌区域的坐标

        private UdpClient udper_ashost, udper_asjoiner;
        private IPEndPoint Ipend;
        private int discard;
        private int Nowhas;

        private Bitmap deskimg;
        private Bitmap yulan;
        private Bitmap mycards_under;
        private Bitmap hiscards_under;
        private Bitmap playzone;
        private Bitmap bu_chu;

        private PlayRule playrule;
        private bool ImHost;
        private bool connected;
        private byte[] sendbuf;
        private byte[] recvbuf;
        private bool playing;
        private bool decleard_;
        private bool first;
        private bool last__send;


        public Form1()
        {

            InitializeComponent();

            try
            {
                deskimg = new Bitmap("..\\..\\resources\\桌面.bmp");
                yulan = new Bitmap("..\\..\\resources\\yulan.bmp");
                mycards_under = new Bitmap("..\\..\\resources\\mycards_under.bmp");
                hiscards_under = new Bitmap("..\\..\\resources\\hiscards_under.bmp");
                playzone = new Bitmap("..\\..\\resources\\playzone.bmp");
                bu_chu = new Bitmap("..\\..\\resources\\buchu.bmp");
                playrule = new PlayRule();
                ImHost = false;
                connected = false;
                location = new Point(50, 400);
                location_playzone = new Point(90, 145);
                //udper_ashost = new UdpClient(10089);
                udper_asjoiner = new UdpClient(0);

                Ipend = new IPEndPoint(0, 10089);
                sendbuf = new byte[255];
                recvbuf = new byte[255];
                playing = false;
                decleard_ = false;
                first = true;
                last__send = true;

                Nowhas = 52;

                discard = 8;            //默认为8张

                cards = new ArrayList();
                hiscards = new ArrayList();
                cardsend = new ArrayList();
                cardrecv = new ArrayList();
                stack = new Stack();

                int i;
                for (i = 9; i <= Nowhas + 8; i++)
                {
                    cards.Add(new Card());
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
            }

        }

        private void Form1_Load(object sender, EventArgs e)
        {

            button1.Enabled = false;
            System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
            groupBox2.Enabled = false;
        }

        private void ReDrawFrm()
        {
            this.CreateGraphics().DrawImage(deskimg, 0, 0);

        }

        private void ClickCard(int index)
        {
            Graphics g = this.CreateGraphics();
            Size recsize = new Size((index == (cards.Count - 1) ? 71 : 15), 96);
            Rectangle rec = new Rectangle(((Card)cards[index]).location, recsize);

            if (((Card)cards[index]).selected)
            {//非选中->选中 

                SolidBrush semiTransBrush = new SolidBrush(Color.FromArgb(128, 0, 0, 255));

                g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.GammaCorrected;  //覆盖绘图时进行灰度修正
                g.FillRectangle(semiTransBrush, rec);

                cardsend.Add(cards[index]);
                CardComparer cardcompare = new CardComparer();  //声明一个Icomparer接口
                cardsend.Sort(cardcompare);              //排序

            }
            else
            {//选中->非选中 
                g.DrawImageUnscaledAndClipped(((Card)cards[index]).cardimg, rec);
                cardsend.Remove(cards[index]);
            }

            int x = 50 + 35;
            int y = 300 + 13;

            g.DrawImage(yulan, 84, 313, 290, 54);
            for (int i = 0; i < cardsend.Count; i++)
            {
                g.DrawImage(((Card)cardsend[i]).cardimg, x, y, 40, 53);
                x += 10;
            }

            int mini = 0;

            if (decleard_)
                button_cancel.Enabled = true;
            else
                button_cancel.Enabled = button_chupai.Enabled = false;

            if (cardsend.Count == 0)
            {
                label_cardselected.Text = "未选牌";
                button_chupai.Enabled = false;
            }

            else if (!playrule.legal(ref cardsend, ref mini))
            {
                label_cardselected.Text = "无此牌型";
                button_chupai.Enabled = false;
            }

            else
            {
                if (playrule.legal(ref cardsend, ref cardrecv))
                {
                    label_cardselected.Text = playrule.cardstype(ref cardsend, ref mini).ToString();
                    if (first && ImHost)
                    {
                        button_chupai.Enabled = true;
                    }

                    if (decleard_)
                        button_chupai.Enabled = true;
                }

                else
                {
                    label_cardselected.Text = "对方大过你哦~";
                    button_chupai.Enabled = false;
                }
            }

        }

        private void ReDrawCards(ref ArrayList al, ref Point Location)
        {//填充牌型(所有充填)

            /* 放弃使用 选中抬高
            int x = ((Card)al[0]).location.X;
            int w = 15 * al.Count + 71;                   //间距15像素*起始张数+71单张宽度
            int y = ((Card)al[0]).location.Y - 20;       //选中后抬高20像素
            int h = 96 + 20;
            */

            Point loc = new Point(Location.X, Location.Y);
            if (al.Count == 0)
            {
                this.CreateGraphics().DrawImage(mycards_under, loc);
                return;
            }
            int x = ((Card)al[0]).location.X;
            int y = ((Card)al[0]).location.Y;
            //int w = 15 * (52-discard)/2 + 71;

            int i = 0;

            if (Location.Equals(location))
            {
                this.CreateGraphics().DrawImage(mycards_under, location);
                for (i = 9; i <= al.Count + 8; i++)
                {//调整cards的横坐标
                    ((Card)al[i - 9]).Init(-1, loc);
                    loc.X += 15;
                }
            }

            for (i = 0; i < al.Count; i++)
            {
                this.CreateGraphics().DrawImage(((Card)al[i]).cardimg, ((Card)al[i]).location);
            }
        }


        private void ReDrawHisCards(int n)
        {//绘制n张对方牌(背面)
            Point loc = new Point(50, 50);

            this.CreateGraphics().DrawImage(hiscards_under, loc);

            for (int i = 0; i < n; i++)
            {
                loc.X = 50 + i * 15;
                this.CreateGraphics().DrawImage(Card.cardback, loc);
            }
        }

        private void ReDrawPlayZone(ref ArrayList al)
        {
            if (al.Count == 0)
            {
                this.CreateGraphics().DrawImage(bu_chu, location_playzone);
                return;
            }
            
            this.CreateGraphics().DrawImage(playzone, location_playzone);
            for (int i = 0; i < al.Count; i++)
            {
                this.CreateGraphics().DrawImage(((Card)al[i]).cardimg, ((Card)al[i]).location);
            }
        }

        private void Form1_MouseClick(object sender, MouseEventArgs e)
        {

            int xx, yy;

            if (cards.Count == 0 || playing == false)
                return;

            xx = location.X;
            yy = location.Y;
            Point left_up = new Point(xx, yy);                          //一列牌的左上角

            int tmp = cards.Count;
            xx = ((Card)cards[(tmp == 0) ? 0 : (tmp - 1)]).location.X;
            yy = ((Card)cards[(tmp == 0) ? 0 : (tmp - 1)]).location.Y;
            Point right_down = new Point(xx, yy);
            right_down.X += 71;                                         //一列牌的右下角
            right_down.Y += 96;



            if (!(e.X > left_up.X && e.X < right_down.X && e.Y > left_up.Y && e.Y < right_down.Y))
                /*if (decleard_ = true)
                {
                    button_cancel.Enabled = false;
                    button_chupai.Enabled = true;
                    return;
                }
                else  */
                return;

            bool storedflag;                        //保存之前的值以取反

            right_down.X -= 71;              //恢复Last Card的左边X坐标

            if (e.X > right_down.X)
            {//最右一张牌
                tmp = cards.Count - 1;
                storedflag = ((Card)cards[tmp]).selected;
                ((Card)cards[tmp]).selected = !storedflag;

            }

            else
            {
                tmp = (e.X - left_up.X) / 15;
                storedflag = ((Card)cards[tmp]).selected;
                ((Card)cards[tmp]).selected = !storedflag;

            }

            ClickCard(tmp);
            /*
            if (storedflag)
            {//如果原来是选中状态 
                ((Card)cards[tmp]).location.Y += 20;
            }
            else
            {
                ((Card)cards[tmp]).location.Y -= 20;
            }
            */
        }

        private void button1_Click_1(object sender, EventArgs e) //发牌
        {//发牌

            int i;
            int nowhas = Nowhas;
            Point loc = new Point(location.X, location.Y);

            for (i = 9; i <= nowhas + 8; i++)
            {

                ((Card)cards[i - 9]).Init(i, loc);
                loc.X += 15;
            }

            int tmp;
            if (nowhas <= discard * 2)
                return;

            //剔除多余的牌
            for (i = 0; i < discard; i++)
            {

                Random d = new Random(unchecked((int)DateTime.Now.Ticks * i));//则 d.Next(52) 满足
                tmp = d.Next(nowhas - i);

                cards.RemoveAt(tmp);                               //从ArrayList中剔出
                nowhas--;
            }

            //发牌
            for (i = 0; i < nowhas / 2; i++)
            {
                Random d = new Random(unchecked((int)DateTime.Now.Ticks * i));
                tmp = d.Next(nowhas - i);

                hiscards.Add(cards[tmp]);
                cards.RemoveAt(tmp);
            }

            nowhas /= 2;

            ReDrawCards(ref cards, ref location);

            /*
            for (i = 0; i < tmp; i++)
                this.CreateGraphics().DrawImage(((Card)hiscards[i]).cardimg, ((Card)hiscards[i]).location);
            */


            button1.Hide();                 //隐藏按钮
            CardComparer cardcompare = new CardComparer();  //声明一个Icomparer接口
            hiscards.Sort(cardcompare);     //排序

            sendbuf[0] = (byte)'B';
            sendbuf[1] = (byte)hiscards.Count;

            for (i = 0; i < hiscards.Count; i++)
            {
                sendbuf[i + 2] = (byte)((Card)hiscards[i]).index;
            }

            playing = true;
            while (connected)
            {
                udper_ashost.Send(sendbuf, sendbuf.Length, Ipend);     //把牌的索引发给对方
                break;
            }
            if (decleard_)
                button_cancel.Enabled = button_chupai.Enabled = true;
            label_game_status.Text = "游戏中";

            /*
            ///////////////////////////////查看对方牌型[测试使用]
            loc.X = 50;
            loc.Y = 200;

            for (i = 0; i < hiscards.Count; i++)
            {
                ((Card)hiscards[i]).location.X = loc.X;
                ((Card)hiscards[i]).location.Y = loc.Y;
                loc.X += 15;
            }

            tmp = hiscards.Count;
            for (i = 0;  i < tmp; i++)
                this.CreateGraphics().DrawImage(((Card)hiscards[i]).cardimg, ((Card)hiscards[i]).location);
           //////////////////////////////
             */


            ReDrawHisCards(hiscards.Count);

            if (cardsend.Count == 0)
            {
                label_cardselected.Text = "请选牌";
                button_chupai.Enabled = false;
            }


        }

        private void button2_Click(object sender, EventArgs e)
        {//出牌按钮

            ///////////////////////发送
            sendbuf[0] = (byte)'C';
            sendbuf[1] = (byte)(cardsend.Count);
            playing = true;
            last__send = true;

            for (int i = 0; i < cardsend.Count; i++)
            {
                sendbuf[i + 2] = (byte)((Card)cardsend[i]).index;
            }

            if (ImHost)
                udper_ashost.Send(sendbuf, cardsend.Count + 2, Ipend);
            else
                udper_asjoiner.Send(sendbuf, cardsend.Count + 2);

            if (ImHost)
                 stack.Push(new CardsBak());
             
            ((CardsBak)stack.Peek()).BackUpSend(ref cardsend);

            /////////////////////////减去已出牌,重绘
            int X = location_playzone.X;
            for (int i = 0; i < cardsend.Count; i++)
            {
                cards.Remove(cardsend[i]);
                ((Card)cardsend[i]).location.X = X;
                ((Card)cardsend[i]).location.Y = location_playzone.Y + 28;
                X += 15;
            }

            if (cards.Count == 0)
            {
                MessageBox.Show("YOU WIN!");
                this.Close();
            }

            int xx = ((Card)cards[cards.Count - 1]).location.X;
            int yy = ((Card)cards[cards.Count - 1]).location.Y;
            xx  += (71);
            yy  += (96 - button2.Size.Height - button_chupai.Size.Height);
            button_chupai.Location = new System.Drawing.Point(xx, yy);

            if (ImHost && first)
            {
                button_chupai.Enabled = false;
            }
            
            decleard_ = false;
            first = false;
            //ReDrawPlayZone(ref cardsend);     //playzone的刷新工作或者可以放到recv处
            ReDrawCards(ref cardsend, ref location_playzone);

            if(cardsend.Count != 0)
                ReDrawCards(ref cards, ref location);
            cardsend.Clear();

        }

        private void button_cancel_Click(object sender, EventArgs e)
        {
            sendbuf[0] = (byte)'C';
            sendbuf[1] = (byte)0;
            playing = true;


            if (ImHost)
            {
                udper_ashost.Send(sendbuf, 2, Ipend);

            }
            else
            {
                udper_asjoiner.Send(sendbuf, 2);
            }

        }

        private void 游戏帮助ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Form_help helpfrm = new Form_help();
            helpfrm.Show();
        }

        private void 关于ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MessageBox.Show("网络工程_软件实习_跑得快2人版, CopyRight@AnyBody", "关于");
        }

        private void 重新开始ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            cards.Clear();
            hiscards.Clear();
            cardsend.Clear();
            cardrecv.Clear();

            cards = new ArrayList();
            hiscards = new ArrayList();
            cardsend = new ArrayList();
            cardrecv = new ArrayList();

            int i;

            for (i = 9; i <= Nowhas + 8; i++)
            {
                cards.Add(new Card());
            }

            button1_Click_1(sender, e);

        }

        private void 新建游戏ToolStripMenuItem_Click(object sender, EventArgs e)
        {//开始等待对方进入游戏
            if (connected)
            {
                MessageBox.Show("已经处于连接状态,要新建游戏请先退出当前游戏", "提示:");
                return;
            }
            button1.Visible = button1.Enabled = true;
            ImHost = true;
            connected = false;

            //控件的可视状态
            groupBox1.Visible = false;
            this.Text += "(Server Mode)";

            textBox1.Text = "正在初始化后台线程";
            try
            {
                udper_ashost = new UdpClient(10089);
                ThreadStart thrstarter = new ThreadStart(Host_Listen_Thread);
                Thread listenthread = new Thread(thrstarter);
                listenthread.IsBackground = true; //转入后台
                listenthread.Start();
            }
            catch (Exception exp)
            {
                MessageBox.Show(exp.ToString(), "出现异常");
            }
        }

        private void Host_Listen_Thread()
        {
            long counter = 0;
            int tmp = 0;
            Point loc = new Point();
            button_chupai.Enabled = true;
            CardComparer cardcompare = new CardComparer();

            textBox1.AppendText("线程启动\r\n等待玩家加入游戏ing...");

            button1.Enabled = false;
            button_chupai.Enabled = false;
            button_cancel.Enabled = false;
            IPEndPoint ipend_bak = new IPEndPoint(Ipend.Address, Ipend.Port);


            try
            {
                while (true)
                {

                    recvbuf = udper_ashost.Receive(ref Ipend);

                    if (counter == 0)
                    {
                        ipend_bak = new IPEndPoint(Ipend.Address, Ipend.Port);
                    }
                    else
                    {
                        if (!ipend_bak.Address.Equals(Ipend.Address))
                        {
                            textBox1.AppendText("\r\n另一玩家[" + Ipend.Address.ToString() + "]试图连接");
                            Ipend.Address = ipend_bak.Address;
                            Ipend.Port = ipend_bak.Port;

                            sendbuf[0] = (byte)'Z';
                            udper_ashost.Send(sendbuf, 1, Ipend);
                            counter++;
                            continue;
                        }
                    }

                    if (recvbuf[0] == 'A')
                    {
                        textBox1.AppendText("\r\n玩家[" + Ipend.Address.ToString() + "] 正在建立连接..");
                        connected = true;       //已经连接到游戏
                        label_game_status.Text = "\r\n 等候发牌";
                        sendbuf[0] = (byte)'A';
                        udper_ashost.Send(sendbuf, 1, Ipend);
                        textBox1.AppendText("\r\n1玩家加入游戏,等待发牌..");
                        label_game_status.Text = "已连接";
                        button1.Enabled = true;

                    }

                    else if (recvbuf[0] == 'C')
                    {
               
                        cardrecv.Clear();
                        decleard_ = true;
                        last__send = false;

                        tmp = (byte)recvbuf[1];

                        loc.X = location_playzone.X;
                        loc.Y = location_playzone.Y;
                        for (int i = 0; i < tmp; i++)
                        {
                            cardrecv.Add(new Card());
                            ((Card)cardrecv[i]).Init((int)recvbuf[i + 2], loc);
                            loc.X += 15;

                            hiscards.RemoveAt(0);
                        }
                        if (hiscards.Count == 0)
                        {
                            MessageBox.Show("Sorry but U have Lost...~");
                            this.Close();
                        }

                        ReDrawPlayZone(ref cardrecv);
                        ((CardsBak)stack.Peek()).BackUpRecv(ref cardrecv);

                        if (tmp != 0)
                        {
                            ReDrawHisCards(hiscards.Count);
                        }
                    }

                    else if (recvbuf[0] == 'I')
                    {
                        recvbuf[0] = recvbuf[1] = (byte)' ';
                        textBox1.AppendText("\r\nTa:" + System.Text.Encoding.Default.GetString(recvbuf));
                    }

                    else if (recvbuf[0] == 'D')
                    {
                        sendbuf[0] = (byte)'E';
                        if (MessageBox.Show("对方要求悔牌,是否同意?", "?", MessageBoxButtons.YesNo) == DialogResult.Yes)
                        {
                            sendbuf[1] = (byte)1;
 
                            cardrecv.Clear();
                            tmp = ((CardsBak)stack.Peek()).recvbak.Count;
                            for (int i = 0; i < tmp; i++)
                            {
                                hiscards.Add(i);
                            }

                            if (tmp != 0)
                            {
                                ReDrawHisCards(hiscards.Count);
                            }
                                

                            tmp = ((CardsBak)stack.Peek()).sendbak.Count;
                            for (int i = 0; i < tmp; i++)
                                cardsend.Add(((CardsBak)stack.Peek()).sendbak[i]);

                            this.CreateGraphics().DrawImage(playzone, location_playzone);
                            ReDrawCards(ref cardsend, ref location_playzone);

                            cardsend.Clear();
                            decleard_ = false;
                            button_chupai.Enabled = button_cancel.Enabled = false;
                        }
                        else
                            sendbuf[1] = (byte)0;
                        udper_ashost.Send(sendbuf, 2, Ipend);

                    }

                    else if (recvbuf[0] == 'E')
                    {
                        if (recvbuf[1] == 1)
                        {
                            decleard_ = true;
                            cardrecv.Clear();

                            tmp = ((CardsBak)stack.Peek()).sendbak.Count;
                            for (int i = 0; i < tmp; i++)
                                cards.Add(((CardsBak)stack.Peek()).sendbak[i]);
                            cards.Sort(cardcompare);
                            stack.Pop();

                            if (stack.Count != 0)
                            {
                                tmp = ((CardsBak)stack.Peek()).recvbak.Count;
                                for (int i = 0; i < tmp; i++)
                                {
                                    cardrecv.Add(((CardsBak)stack.Peek()).recvbak[i]);
                                }

                                ReDrawPlayZone(ref cardrecv);
                            }
                            else
                                this.CreateGraphics().DrawImage(playzone, location_playzone);
                            ReDrawCards(ref cards, ref  location);
                            button_chupai.Enabled = true;
                            button_cancel.Enabled = true;

                        }
                        else
                            MessageBox.Show("对方不允许此次悔牌");
                    }

                    else
                        continue;

                    counter++;
                }
            }
            catch (Exception exp)
            {
                MessageBox.Show(exp.ToString(), "遇到异常");
            }

        }

        private void 加入游戏ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ImHost = false;
            button1.Visible = false;

            if (connected || playing)
            {
                MessageBox.Show("已经连接到游戏,必须退出当前游戏才可以加入新游戏", "提示:");
                return;
            }
            this.Text += "(Client Mode)";

            string ipstr = numericUpDown1.Value.ToString() + "." + numericUpDown2.Value.ToString() + "." +
                numericUpDown3.Value.ToString() + "." + numericUpDown4.Value.ToString();

            try
            {
                udper_asjoiner.Connect(IPAddress.Parse(ipstr), (int)numericUpDown5.Value);

                //send connecting request;
                sendbuf[0] = (byte)'A';

                udper_asjoiner.Send(sendbuf, 1);
                textBox1.AppendText("发出连接请求...正在等待回应...");
                label_game_status.Text = "正在连接";

                groupBox1.Enabled = false;
            }

            catch (Exception exp)
            {
                MessageBox.Show(exp.ToString(), "运行时异常");

            }

            textBox1.AppendText("\r\n创建监听线程ing...");
            try
            {
                ThreadStart thrstarter = new ThreadStart(Joiner_Listen_Thread);
                Thread listenthread = new Thread(thrstarter);
                listenthread.IsBackground = true;
                listenthread.Start();
            }
            catch (Exception exp)
            {
                MessageBox.Show(exp.ToString(), "新建线程时出现异常");
            }

        }

        private void Joiner_Listen_Thread()
        {
            //groupBox1.Visible = false;

            textBox1.AppendText("\r\n监听线程创建完毕..");
            int tmp = 0;
            int nowhas = 0;
            Point loc = new Point();
            CardComparer cardcompare = new CardComparer();

            try
            {
                while (true)
                {

                    recvbuf = udper_asjoiner.Receive(ref Ipend);

                    if (recvbuf[0] == 'A')
                    {
                        connected = true;                   //更改连接标志
                        label_game_status.Text = "已经连接";
                        button1.Visible = groupBox1.Visible = false;
                        button_chupai.Enabled = button_cancel.Enabled = false;

                        textBox1.AppendText("\r\nConnected, 等待发牌~");
                    }

                    else if (recvbuf[0] == 'Z')
                    {
                        textBox1.AppendText("\r\n****对方已经开始游戏****");
                        label_game_status.Text = "连接断开";
                    }

                    else if (recvbuf[0] == 'B')
                    {
                        textBox1.AppendText("\r\nGame Starting...");
                        cards.Clear();      //清空本地存牌
                        hiscards.Clear();
                        nowhas = (int)recvbuf[1];

                        loc.X = location.X;
                        loc.Y = location.Y;

                        for (int i = 0; i < nowhas; i++)
                        {
                            cards.Add(new Card());
                            ((Card)cards[i]).Init((int)recvbuf[i + 2], loc);
                            loc.X += 15;

                            hiscards.Add(nowhas);       //滥竽充数一下
                        }
                        textBox1.AppendText("\r\n获得" + nowhas.ToString() + "张牌\r\n等待主机出牌ing");
                        label_game_status.Text = "等待出牌";

                        ReDrawCards(ref cards, ref location);
                        ReDrawHisCards(hiscards.Count);
                        playing = true;

                    }
                    else if (recvbuf[0] == 'C')
                    {
                        label_game_status.Text = "游戏中(勿扰谢谢配合)";
                        cardrecv.Clear();
                        tmp = (int)recvbuf[1];

                        decleard_ = true;
                        last__send = false;

                        loc.X = location_playzone.X;
                        loc.Y = location_playzone.Y;

                        for (int i = 0; i < tmp; i++)
                        {
                            cardrecv.Add(new Card());
                            ((Card)cardrecv[i]).Init((int)recvbuf[i + 2], loc);
                            loc.X += 15;

                            hiscards.RemoveAt(0);       //继续滥竽充数...
                        }

                        if (hiscards.Count == 0)
                        {
                            MessageBox.Show("Sorry but U have Lost...~");
                            this.Close();
                        }

                        button_chupai.Enabled = true;

                        ReDrawPlayZone(ref cardrecv);

                        stack.Push(new CardsBak());
                        ((CardsBak)(stack.Peek())).BackUpRecv(ref cardrecv);
                        
                         if(tmp != 0)
                        {
                            ReDrawHisCards(hiscards.Count);
                        }
                    }

                    else if (recvbuf[0] == 'I')
                    {
                        recvbuf[0] = recvbuf[1] = (byte)' ';
                        textBox1.AppendText("\r\nTa:" + System.Text.Encoding.Default.GetString(recvbuf));
                    }

                    else if (recvbuf[0] == 'D')
                    {
                        sendbuf[0] = (byte)'E';
                        if (MessageBox.Show("对方要求悔牌,是否同意?", "?", MessageBoxButtons.YesNo) == DialogResult.Yes)
                        {
                            sendbuf[1] = (byte)1;
                            cardrecv.Clear();
                            tmp = ((CardsBak)stack.Peek()).recvbak.Count;
                            for (int i = 0; i < tmp; i++)
                            {
                                hiscards.Add(i);
                            }
                            if (tmp != 0)
                            {
                                ReDrawHisCards(hiscards.Count);
                            }
                            stack.Pop();

                            if (stack.Count != 0)
                            {
                                tmp = ((CardsBak)stack.Peek()).recvbak.Count;
                                for (int i = 0; i < tmp; i++)
                                    cardrecv.Add(((CardsBak)stack.Peek()).recvbak[i]);

                                ReDrawPlayZone(ref cardrecv);
                                ReDrawCards(ref cardsend, ref location_playzone);
                            }
                            else
                                this.CreateGraphics().DrawImage(playzone, location_playzone);
                            decleard_ = false;
                            button_chupai.Enabled = button_chupai.Enabled = false;
                        }
                        else
                            sendbuf[1] = (byte)0;
                        udper_asjoiner.Send(sendbuf, 2);

                    }

                    else if (recvbuf[0] == 'E')
                    {
                        if (recvbuf[1] == 1)
                        {
                            cardrecv.Clear();
                            tmp = ((CardsBak)stack.Peek()).recvbak.Count;
                            for (int i = 0; i < tmp; i++)
                            {
                                cardrecv.Add(((CardsBak)stack.Peek()).recvbak[i]);
                            }


                            tmp = ((CardsBak)stack.Peek()).sendbak.Count;
                            for (int i = 0; i < tmp; i++)
                                cards.Add(((CardsBak)stack.Peek()).sendbak[i]);
                            cards.Sort(cardcompare);

                            ReDrawPlayZone(ref cardrecv);
                            ReDrawCards(ref cards, ref location);

                            decleard_ = true;
                            button_chupai.Enabled = true;
                            button_cancel.Enabled = true;

                        }
                        else
                            MessageBox.Show("对方不允许此次悔牌");
                    }

                }


            }
            catch (Exception exp)
            {
                MessageBox.Show(exp.ToString());

            }

        }

        private void button_connect_Click(object sender, EventArgs e)
        {
            加入游戏ToolStripMenuItem_Click(sender, e);
        }

        private void 张ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (playing || !ImHost)
                MessageBox.Show("只能在发牌之前设置<而且必须是游戏创建者>");
            else
            {
                discard = 8;
                textBox1.AppendText("\r\n 本次游戏将会随即排除8张牌");
            }
        }
        private void 张ToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            if (playing || !ImHost)
                MessageBox.Show("只能在发牌之前设置<而且必须是游戏创建者>");
            else
            {
                discard = 10;
                textBox1.AppendText("\r\n 本次游戏将会随即排除10张牌");
            }
        }

        private void button2_Click_1(object sender, EventArgs e)
        {
            新建游戏ToolStripMenuItem_Click(sender, e);
        }

        private void button_sendmsg_Click(object sender, EventArgs e)
        {
            if (!connected)
            {
                textBox1.AppendText("\r\n没有游戏连接,暂不能发言..囧");
                return;
            }

            textBox1.AppendText( "\r\nMe:" + textBox_msg.Text);

            byte[] swap =new byte[250];

            sendbuf[0] = (byte)'I';
            swap = System.Text.Encoding.Default.GetBytes(textBox_msg.Text);
            sendbuf[1] = (byte) swap.Length;
            swap.CopyTo(sendbuf, 2);
            
            if (ImHost)
            {
                udper_ashost.Send(sendbuf, swap.Length, Ipend);
            }
            else
            {
                udper_asjoiner.Send(sendbuf, swap.Length);
            }
        }

        private void 我要悔牌ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (!playing)
            {
                MessageBox.Show("游戏还没有开始呢..囧");
                return;
            }

            if (!last__send)
            {
                MessageBox.Show("只有在对方出牌之前才可以悔牌啊~~~");
                return;
            }

            sendbuf[0] = (byte)'D';
            if (ImHost)
                udper_ashost.Send(sendbuf, 1, Ipend);
            else
                udper_asjoiner.Send(sendbuf, 1);
        }

        /*
        private void 退出ToolStripMenuItem_Click(object sender, CancelEventArgs e)
        {
            sendbuf[0] = (byte)'X';
            if (ImHost)
                udper_ashost.Send(sendbuf, 1, Ipend);
            else
                udper_asjoiner.Send(sendbuf, 1);
            e.Cancel = true;
        }*/
    }

    public class CardsBak
    {
        public ArrayList sendbak;
        public ArrayList recvbak;

        public CardsBak()
        {
            sendbak = new ArrayList();
            recvbak = new ArrayList();
        }

        public void BackUpSend(ref ArrayList al)
        {
            this.BackUp(ref sendbak,ref  al);
        }

        public void BackUpRecv(ref ArrayList al)
        {
            this.BackUp(ref recvbak,ref al);
        }

        private void BackUp(ref ArrayList dest, ref ArrayList source)
        {
            for (int i = 0; i < source.Count; i++)
            {
                dest.Add(source[i]);
            }
        }


    }

    public class CardComparer : IComparer
    {
        int IComparer.Compare(object a, object b)
        {
            Card c1 = (Card)a;
            Card c2 = (Card)b;
            if (c1.index > c2.index)
                return 1;
            if (c1.index < c2.index)
                return -1;
            else
                return 0;
        }
    }


    public class Card
    {
        public int index, num, type;
        public Image cardimg;
        public Point location;
        public bool selected;
        public static Image cardback;
 
        private string pathname;

        public Card()
        {
            selected = false;
            this.pathname = "..\\..\\resources\\背面.bmp";
            this.cardimg = new Bitmap(pathname);
            cardback = new Bitmap(pathname);
            this.location = new Point(0,0);

            num = index = type = 0;
        }
     
        public Card(int Index, Point Location)
        {
            selected = false;
            this.index = Index;
            this.location = new Point(Location.X, Location.Y);
            //this.cardimg = new Bitmap("..\\..\\resources\\背面.bmp");
            this.pathname = "..\\..\\resources\\";
            

            num = (index + 3) / 4;
            type = index % 4 == 0 ? 4 : index % 4;

        }

        public void Init(int Index, Point Location)
        {//Index ==-1时忽略
            if (Index != -1)
            {
                index = Index;
                num = (index + 3) / 4;
                type = index % 4 == 0 ? 4 : index % 4;
            }
            location = Location;

            pathname = "..\\..\\resources\\";
            pathname += index.ToString();
            pathname += ".bmp";

            cardimg =new Bitmap(pathname);
        
        }

    }

    public enum CardsType {单张, 对, 连对, 三同张, 连三同张, 三同张带一, 连三同张带, 顺, 炸弹 ,非法};

    public class PlayRule
    {
        
        public bool legal(ref ArrayList mine, ref int mini)
        {
            if (cardstype(ref mine, ref mini) != CardsType.非法)
                return true;
            else
                return false;
        }
        public bool legal(ref ArrayList mine,ref ArrayList his)
        {
            int mymini = 0;
            int hismini = 0;

            CardsType mytype, histype;

            mytype = cardstype(ref mine, ref mymini);       //获得我方牌型和 测试基准牌
            histype = cardstype(ref his, ref hismini);      //获得对方牌型和 测试基准牌

            if (his.Count == 0)    //对方不出牌||第一次出牌
            {
                if (!legal(ref mine, ref mymini))
                    return false;
                else if (his.Count == 0)
                    return true;
            }

            if (mytype!=histype || mine.Count != his.Count)
            {
                if (mytype != CardsType.炸弹)
                    return false;
                else //mycard一定是炸弹&&对方的牌型一定不是炸弹
                  return true;
            }

            if (mymini > hismini)
                return true;
           
            return false;
        }

        public CardsType cardstype(ref ArrayList al, ref int mini)
        {//////////////////////当返回"非法"类型时, mini值不可用
            
            CardsType type = CardsType.非法;

            switch (al.Count)
            {
                case 1:
                    {
                        type = CardsType.单张;
                        mini = ((Card)al[0]).num;
                        break;
                    }
                case 2:
                    {
                        if (((Card)al[0]).num == ((Card)al[1]).num)
                        {
                            type = CardsType.对;
                            mini = ((Card)al[0]).num;
                        }
                        else
                            type = CardsType.非法;
                        break;
                    }
                case 3:
                    {
                        int swap;
                        swap = ((Card)al[0]).num;
                        type = CardsType.三同张;
                        mini = ((Card)al[0]).num;
                        for (int i = 1; i < al.Count; i++)
                        {
                            if (swap != ((Card)al[i]).num)
                            {
                                type = CardsType.非法;
                                break;
                            }
                        }
                        break;
                    }
                case 4://三同张带一, 连对, 炸弹,非法 
                    {
                        if(liandui(ref al, ref mini))
                            return CardsType.连对;
                        if(bomb(ref al, ref mini))
                            return CardsType.炸弹;

                        int swap = ((Card)al[0]).num;
                        int swap2 = swap;
                        int counter, counter2;
                        counter = counter2 =0;
                        for (int i = 0; i < 4; i++)
                        {
                            swap2 = ((Card)al[i]).num;

                            if (swap == ((Card)al[i]).num)
                                counter++;
                            
                            else 
                            {
                                counter2 = 0;
                                for (int j = 0; j < 4; j++)
                                {
                                    if (swap2 == ((Card)al[j]).num)
                                        counter2++;
                                    
                                }

                            }
                         
                        }
                        mini = (counter > counter2) ? swap : swap2;
                        if ((counter + counter2) == 4 && (counter * counter2) == 3)
                            return CardsType.三同张带一;
                        else
                            return CardsType.非法;
        
                    }

                case 5:
                case 7:
                case 11:
                case 13:
                case 17:
                case 19:
                    { //顺,非法
                        if (shun(ref al, ref mini))
                            return CardsType.顺;
                        else
                            return CardsType.非法;
  
                    }
                case 6:
                case 18:
                    {//顺,连对,连三同张,非法 
                        if (shun(ref al, ref mini))
                            return CardsType.顺;
                        if (liandui(ref al, ref mini))
                            return CardsType.连对;
                        if (liansantongzhang(ref al, ref mini))
                            return CardsType.连三同张;
                        else
                            return CardsType.非法;

                    }

                case 8:
                case 16:
                case 20:
                    {//顺,连对,连三同张带,非法 
                        if (shun(ref al, ref mini))
                            return CardsType.顺;
                        if (liandui(ref al, ref mini))
                            return CardsType.连对;
                        if (liansantongzhangDai(ref al, ref mini))
                            return CardsType.连三同张带;
                        else
                            return CardsType.非法;

                    }
                case 9:
                case 15:
                case 21:
                    {//顺, 连三同张 , 非法
                        if (shun(ref al, ref mini))
                            return CardsType.顺;
                        if (liansantongzhang(ref al, ref mini))
                            return CardsType.连三同张;
                        else
                            return CardsType.非法;
                    
                    }
                case 10:
                case 14:
                case 22:
                    { //顺, 连对,非法
                        if (shun(ref al, ref mini))
                            return CardsType.顺;
                        if (liandui(ref al, ref mini))
                            return CardsType.连对;
                        else
                            return CardsType.非法;
                    
                    }
                case 12:
                    { //顺, 连对, 连三同张,连三同张带, 非法
                        if (shun(ref al, ref mini))
                            return CardsType.顺;
                        if (liandui(ref al, ref mini))
                            return CardsType.连对;
                        if (liansantongzhang(ref al, ref mini))
                            return CardsType.连三同张;
                        if (liansantongzhangDai(ref al, ref mini))
                            return CardsType.连三同张带;
                        else
                            return CardsType.非法;
                    
                    }
            }

            return type;
        }

        private bool bomb(ref ArrayList al, ref int mini)
        {//4张牌(类内部调用) 

            int swap;
            if (al.Count != 4)
                return false;

            swap = ((Card)al[0]).num;
            for(int i = 0; i<4; i++)
            {
                if (swap != ((Card)al[i]).num)
                    return false;
            }

            mini = ((Card)al[0]).num;
            return true;
        }
        
        private bool shun(ref ArrayList al, ref int mini)
        {//牌数2~xxx(类内部调用)

            int swap_0, swap_1;

            swap_0 = al.Count;

            if (swap_0 < 2)
                return false;

            if (((Card)al[swap_0 -1]).num == 15 || ((Card)al[0]).num == 15)
                return false;

            for (int i =swap_0=swap_1= 0; i < al.Count - 1; i++)
            {
                if ((i != 0) && swap_1 != swap_0)
                    return false;

                swap_0 = ((Card)al[i + 1]).num - ((Card)al[i]).num;
                if (swap_0 == 1 || swap_0 == -1)
                {
                    swap_1 = swap_0;
                }
                else
                    return false;

            }

            swap_0 = al.Count;
            mini = ((((Card)al[0]).num - ((Card)al[1]).num) < 0 ? ((Card)al[0]).num : ((Card)al[swap_0 -1]).num);
            return true;
        
        }

        private bool liandui(ref ArrayList al, ref int mini)
        {//牌数4~xxx(类内部调用)
            ArrayList tmpal = new ArrayList(al.Count/2);
            for (int i = 0; i < al.Count; i += 2)
            {
                tmpal.Add(al[i]);
            }
            if (shun(ref tmpal, ref mini))
            {
                tmpal.Clear();
                for (int i = 1; i < al.Count; i += 2)
                {
                    tmpal.Add(al[i]);
                }
                if (shun(ref tmpal, ref mini))
                {
                    if (((Card)al[0]).num == ((Card)al[1]).num)
                        return true;
                    else
                        return false;
                }
                else
                    return false;
            }
            else
                return false;
              
        }

        private bool liansantongzhang(ref ArrayList al, ref int mini)
        {//牌数6~xxx(类内部调用)
            ArrayList tmpal = new ArrayList(al.Count / 3);
            for (int i = 0; i < al.Count; i += 3)
            {
                tmpal.Add(al[i]);
            }
            if (shun(ref tmpal, ref mini))
            {
                tmpal.Clear();
                for (int i = 1; i < al.Count; i += 3)
                {
                    tmpal.Add(al[i]);
                }
                if (shun(ref tmpal, ref mini))
                {
                    tmpal.Clear();
                    for (int i = 1; i < al.Count; i += 3)
                    {
                        tmpal.Add(al[i]);
                    }

                    if (shun(ref tmpal, ref mini))
                    {
                        if (((Card)al[0]).num == ((Card)al[1]).num && ((Card)al[0]).num == (((Card)al[2]).num))
                            return true;
                        else
                            return false;
                    }
                    else
                        return false;
                }
                else
                    return false;
            }
            else
                return false;
        
        }

        private bool liansantongzhangDai(ref ArrayList al, ref int mini)
        {//8~xxx(类内部调用)::连三同张带
            ArrayList tmpal = new ArrayList();
            for (int i = 0; i < al.Count; i++)
            {
                tmpal.Add(al[i]);
            }

            int swap = 0;
            int count1 = 0;

            for (int i = 0; i < tmpal.Count; i++)
            {
                swap = ((Card)tmpal[i]).num;
                count1 = 0;

                for(int j = 0; j < tmpal.Count; j++)
                {
                    if(swap == ((Card)tmpal[j]).num)
                        count1 ++;
                }
                if (count1 != 3)
                {
                    tmpal.RemoveAt(i);
                    i--;
                }
            }

            if ((tmpal.Count % 3 )!= 0)
                return false;

            if (liansantongzhang(ref tmpal, ref mini))
                return true;
            else
                return false;
        }


    }
}

